package org.javaforever.gatescore.core;

import java.io.Serializable;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;

import org.javaforever.gatescore.utils.StringUtil;

public class FrontDomain implements Comparable<FrontDomain>,Cloneable,Serializable {
	private static final long serialVersionUID = 3837396581335617651L;
	protected Set<FrontMethod> setters = new TreeSet<FrontMethod>();
	protected Set<FrontMethod> getters = new TreeSet<FrontMethod>();
	protected FrontField domainId;
	protected FrontField domainName;
	protected FrontField active;
	protected Set<FrontField> fields = new TreeSet<FrontField>();
	protected String plural; 
	protected String label;
	protected Map<String,String> fieldLabels = new TreeMap<String,String>();
	protected Map<String,String> mtmLabels = new TreeMap<String,String>();
	protected Set<FrontManyToMany> manyToManies = new TreeSet<FrontManyToMany>();
	protected String alias = "";
	protected String aliasLabel = "";
	protected String aliasPlural = "";
	protected String standardName;
	protected String packageToken;
	protected boolean useController = false;
	
	public boolean isUseController() {
		return useController;
	}

	public void setUseController(boolean useController) {
		this.useController = useController;
	}

	@Override
	public int compareTo(FrontDomain o) {
		return this.standardName.compareTo(o.getStandardName());
	}
	
	public void putMtmLabel(String key,String value){
		this.mtmLabels.put(key, value);
	}
	
	public Set<FrontField> getFieldsWithoutId(){
		Set<FrontField> set = new TreeSet<FrontField>();
		set.addAll(this.getFields());		
		if (this.domainName != null) {
			this.domainName.setSerial(this.maxSerial() + 100);
			set.add(this.domainName);
		}
		if (this.active != null) {
			this.active.setSerial(this.maxSerial() + 200);
			set.add(this.active);
		}
		return set;
	}
	
	public long maxSerial(){
		long maxserial = 0;
		for (FrontField f:this.fields){
			if (f.getSerial() > maxserial) maxserial = f.getSerial();
		}
		return maxserial;
	}
	
	public void decorateDomainWithLabels(){
		for (FrontField f: this.getFields()){
			String label = this.fieldLabels.get(f.getLowerFirstFieldName());
			if (label!=null && !label.equals("")) f.setLabel(label);
		}
		for (FrontManyToMany mtm: this.getManyToManies()){
			String label = this.mtmLabels.get(mtm.getSlaveAlias());
			if (label!=null && !label.equals("")) mtm.setSlaveAliasLabel(label);
		}
	}
	
	public Set<FrontDropdown> getDropdownSet(){
		Set<FrontDropdown> dropdowns = new TreeSet<FrontDropdown>(new FrontDropdownDomainComparator());
		for (FrontField ff:this.getFields()) {
			if (ff instanceof FrontDropdown) {
				FrontDropdown dp = (FrontDropdown) ff;
				dropdowns.add(dp);
			}			
		}
		return dropdowns;
	}
	
	public String getText(){
		if (!StringUtil.isBlank(this.getAliasLabel())){
			return this.getAliasLabel();
		}
		else if (!StringUtil.isBlank(this.getLabel())) {
			return this.label;
		}
		else if (!StringUtil.isBlank(this.getAlias())) {
			return this.getAlias();
		}		
		else return this.getStandardName();
	}
	
	public Object clone() {
		FrontDomain o = null;
		try {
			o = (FrontDomain) super.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return o;
	}
	
	public String getLowerFirstDomainName(){
		return StringUtil.lowerFirst(this.getStandardName());
	}
	
	public String getLowerFirstChar(){
		return StringUtil.lowerFirst(this.getStandardName()).substring(0,1);
	}
	
	public String getCapFirstDomainName(){
		return StringUtil.capFirst(this.getStandardName());
	}
	
	public String getCapFirstPlural(){
		return StringUtil.capFirst(this.getPlural());
	}
	
	public String getLowerFirstPlural(){
		return StringUtil.lowerFirst(this.getPlural());
	}
	
	public Set<FrontMethod> getSetters() {
		return setters;
	}
	public void setSetters(Set<FrontMethod> setters) {
		this.setters = setters;
	}
	public Set<FrontMethod> getGetters() {
		return getters;
	}
	public void setGetters(Set<FrontMethod> getters) {
		this.getters = getters;
	}
	public FrontField getDomainId() {
		return domainId;
	}
	public void setDomainId(FrontField domainId) {
		this.domainId = domainId;
	}
	public FrontField getDomainName() {
		return domainName;
	}
	public void setDomainName(FrontField domainName) {
		this.domainName = domainName;
	}
	public FrontField getActive() {
		return active;
	}
	public void setActive(FrontField active) {
		this.active = active;
	}
	public String getPlural() {
		if (this.plural == null || "".equals(this.plural)){
			return PluralUtil.lookupPlural(this.standardName);
		} else {
			return StringUtil.capFirst(plural);
		}
	}
	public void setPlural(String plural) {
		this.plural = plural;
	}
	public String getLabel() {
		return label;
	}
	public void setLabel(String label) {
		this.label = label;
	}
	public Map<String, String> getFieldLabels() {
		return fieldLabels;
	}
	public void setFieldLabels(Map<String, String> fieldLabels) {
		this.fieldLabels = fieldLabels;
	}
	public Map<String, String> getMtmLabels() {
		return mtmLabels;
	}
	public void setMtmLabels(Map<String, String> mtmLabels) {
		this.mtmLabels = mtmLabels;
	}
	public Set<FrontManyToMany> getManyToManies() {
		return manyToManies;
	}
	public void setManyToManies(Set<FrontManyToMany> manyToManies) {
		this.manyToManies = manyToManies;
	}
	public String getAlias() {
		return alias;
	}
	public void setAlias(String alias) {
		this.alias = alias;
	}
	public String getAliasLabel() {
		return aliasLabel;
	}
	public void setAliasLabel(String aliasLabel) {
		this.aliasLabel = aliasLabel;
	}
	public String getAliasPlural() {
		return aliasPlural;
	}
	public void setAliasPlural(String aliasPlural) {
		this.aliasPlural = aliasPlural;
	}
	public String getStandardName() {
		return standardName;
	}
	public void setStandardName(String standardName) {
		this.standardName = standardName;
	}

	public Set<FrontField> getFields() {
		return fields;
	}

	public void setFields(Set<FrontField> fields) {
		this.fields = fields;
	}
	
	public void addField(FrontField field) {
		this.fields.add(field);
	}
	
	public Set<FrontField> getAllFields() {
		Set<FrontField> retVals = new TreeSet<FrontField>();
		retVals.addAll(this.fields);
		retVals.add(this.domainId);
		retVals.add(this.domainName);
		retVals.add(this.active);
		return retVals;
	}
	
	public Set<FrontField> getAllFieldsWithoutId(){
		Set<FrontField> retVals = new TreeSet<FrontField>();
		retVals.addAll(this.fields);
		retVals.add(this.domainName);
		retVals.add(this.active);
		return retVals;
	}
	
	public String getAliasOrNamePlural() {
		if (StringUtil.isBlank(this.alias)){
			return getPlural();
		}
		if (StringUtil.isBlank(this.aliasPlural)){
			return PluralUtil.lookupPlural(this.getAlias());
		} else {
			return StringUtil.capFirst(this.aliasPlural);
		}
	}

	public void addManyToMany(FrontManyToMany mtm) {
		this.manyToManies.add(mtm);
		
	}	
	
	public String getAliasOrName() {
		if (!StringUtil.isBlank(this.getAlias())) {
			return this.getAlias();
		}else {
			return this.getStandardName();
		}
	}

	public void setFieldValue(String aliasName, String fieldValue) {
		// TODO Auto-generated method stub
		
	}

	public void putFieldLabel(String fieldname, String fieldLabel) {
		// TODO Auto-generated method stub
		
	}

	public FrontField getField(String fieldName) {
		// TODO Auto-generated method stub
		return null;
	}

	public String getPackageToken() {
		return packageToken;
	}

	public void setPackageToken(String packageToken) {
		this.packageToken = packageToken;
	}
}
